<?php
namespace app\factory\common;

use JsonSerializable;
use IteratorAggregate;
use Serializable;

abstract class Readonly implements JsonSerializable, IteratorAggregate, Serializable
{
    /**
     * @var array
     */
    protected $data;

    protected $protected = [];

    public function __construct( $data = [] )
    {
        $this->data = $data;
    }

    public function __get($name)
    {
        return isset( $this->data[$name] ) ? $this->data[$name] : null;
    }

    public function __set($name, $value)
    {
        if( ! isset( $this->protected[$name] ) ){
            $this->data[$name] = $value;
        }
    }

    public function __isset($name)
    {
        return isset( $this->data[$name] );
    }

    public function __unset($name)
    {
        if( ! isset( $this->protected[$name] ) ){
            unset( $this->data[$name] );
        }
    }

    /**
     * @inheritDoc
     */
    public function jsonSerialize()
    {
        return $this->data;
    }

    /**
     * @inheritDoc
     */
    public function getIterator()
    {
        foreach ( $this->data as $key => $datum ){
            yield $key => $datum;
        }
    }

    /**
     * @inheritDoc
     */
    public function serialize()
    {
        return serialize($this->data);
    }

    /**
     * @inheritDoc
     */
    public function unserialize($serialized)
    {
        $this->data = unserialize($serialized);
    }

    /**
     * 设置data
     * @param array $data
     * @param bool $clean
     */
    public function setData( $data, $clean = false ){
        if( $clean ){
            foreach ( $this->data as $key => $datum ){
                if( ! isset( $data[$key] ) ){
                    $this->__unset($key);
                }
            }
        }
        foreach ( $data as $key => $datum ){
            $this->__set($key, $datum);
        }
    }

    /**
     * 获取整个data
     * @return array
     */
    public function getData(){
        return $this->data;
    }
}